package cathttp

///
// * 缓冲库
// * 创建于: 2019-7-13
// * 修改于: 2019-7-14
// * 版本: 0.0.1
// ! -----------------
// ? Buffer
// *   |- Call:Get
// *   |       |
// *   |       ?-(len(chainList) == chainQuantity)
// *   |       |                  |
// *   |       |                  X- Call:New
// *   |       X-(len(chainList) != chainQuantity)
// *   |                          |
// *   |                          X-chainList[chainQuantity]
// * chainList
// *    [BufferValue,BufferValue,BufferValue,BufferValue,BufferValue,...]
// *          ↑          ↑- chainQuantity
// *          X------------ Buffer.inform
///

// BufferValue 缓冲数据
type BufferValue struct {
	id     int
	inform *chan int
	Value  interface{} // * 数据
	Employ bool        // * 标记
}

// Release 释放
func (Buffer *BufferValue) Release() {
	Buffer.Employ = true
	*Buffer.inform <- Buffer.id
}

// Buffer 缓冲类
type Buffer struct {
	// * 构建器
	New     func() interface{}
	Release func([]*BufferValue)
	// * 参数
	lock    chan bool
	inform  chan int
	cycleID int64
	// * 管理列表
	chainList     []*BufferValue
	chainQuantity int // * 已用数量
}

// Init 初始化
func (Buffer *Buffer) Init(Time int64) *Buffer {
	// * 初始化
	Buffer.lock = make(chan bool, 1)
	Buffer.inform = make(chan int)
	// * 销毁周期
	Buffer.cycleID = Cycle.Add(Time, func() {
		Buffer.lock <- true
		// * 释放
		if Buffer.Release != nil {
			Buffer.Release(Buffer.chainList[Buffer.chainQuantity:])
		}
		// * 重置
		Buffer.chainList = Buffer.chainList[:Buffer.chainQuantity]
		<-Buffer.lock
	})
	// * 调度
	go func() {
		for {
			id := <-Buffer.inform // * 等待释放
			Buffer.lock <- true
			Buffer.chainQuantity-- // * 减少已用数量
			// * 交换变量
			Buffer.chainList[id], Buffer.chainList[Buffer.chainQuantity] = Buffer.chainList[Buffer.chainQuantity], Buffer.chainList[id] // * 交换释放的最后占用
			// * 还原自身 ID
			Buffer.chainList[id].id, Buffer.chainList[Buffer.chainQuantity].id = id, Buffer.chainQuantity
			<-Buffer.lock
		}
	}()
	return Buffer
}

// Get 得到
func (Buffer *Buffer) Get() (Value *BufferValue) {
	Buffer.lock <- true
	if len(Buffer.chainList) == Buffer.chainQuantity {
		Value = &BufferValue{
			id:     Buffer.chainQuantity,
			inform: &Buffer.inform,
			Value:  Buffer.New(),
			Employ: true,
		}
		Buffer.chainList = append(Buffer.chainList, Value)
	} else {
		Value = Buffer.chainList[Buffer.chainQuantity]
		Value.Employ = true
	}
	Buffer.chainQuantity++
	<-Buffer.lock
	return
}

// GetQuantity  得到已用数量
func (Buffer *Buffer) GetQuantity() int {
	return Buffer.chainQuantity
}

// GetSize 得到大小
func (Buffer *Buffer) GetSize() int {
	return len(Buffer.chainList)
}
